package com.pb.service.boot.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.pb.infra.auth.entity.custom.LedingOutFile;
import com.pb.infra.auth.service.LeadingOutService;
import com.pb.infra.oth.util.*;
import com.pb.infra.param.service.CapBaseInfoConfigService;
import lombok.Setter;
import org.springframework.core.env.Environment;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * 异步导出
 *
 * @Author: liaohaoyuan
 * @Date: 2021/4/28
 */
public class ExcelThread implements Runnable{

    @Setter
    Map<String,Object> map;
    @Setter
    String userId;
    @Setter
    String serialNumber;
    @Setter
    String fileName;

    private static Pattern FilePattern = Pattern.compile("[\\s\\.:?<>|]");

    @Override
    public void run(){
        try {
            CapBaseInfoConfigService infoConfigService = SpringContextUtil.getBean(CapBaseInfoConfigService.class);
            // 获取数据库中获取保存路径
            String url = infoConfigService.select(Constant.CAP_EXT_FILE_URL,Constant.SYSTEM_ENVIRONMENT);
            String fileNames= serialNumber+".xlsx";
            Date date = new Date();
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String fileFolderName = url+File.separator +format.format(date);
            String fileTime = format1.format(date);
            fileFolderName = filenameFilter(fileFolderName);
            File file = new File(fileFolderName);
            if(!file.exists()){
                file.mkdirs();
            }
            FileOutputStream out = new FileOutputStream(filenameFilter(fileFolderName + File.separator  + fileNames));
            try {
                List<List<Map<String,Object>>> data=JSON.parseObject(JSONArray.toJSONString((JSONArray) map.get("data")), List.class);
                String[][] title=JSON.parseObject(JSONArray.toJSONString((JSONArray) map.get("title")), String[][].class);//获取列头
                if (JsonUtils.isJsonArray(title[0][0])){
                    String[][][] titlename=JSON.parseObject(JSONArray.toJSONString((JSONArray) map.get("title")), String[][][].class);//获取列头
                    String[][][] comments=JSON.parseObject(JSONArray.toJSONString((JSONArray) map.get("comments")), String[][][].class);//获取批注
                    String[][] order=JSON.parseObject(JSONArray.toJSONString((JSONArray) map.get("order")), String[][].class);//数据序列
                    String[][] dataType=JSON.parseObject(JSONArray.toJSONString((JSONArray) map.get("dataType")), String[][].class);//字段数据类型
                    String[] jobBookName=JSON.parseObject(JSONArray.toJSONString((JSONArray) map.get("jobBookName")), String[].class);//工作簿名
                    Map<String,Object> condition=JSON.parseObject(JSONArray.toJSONString(map.get("condition")), HashMap.class);//工作簿名
                    if (title.length==0||jobBookName.length==0||map.size()==0||order.length==0){
                        throw new NullPointerException("数据格式异常");
                    }
                    Boolean contentMerge = map.get("contentMerge") == null?true:(Boolean)map.get("contentMerge");
                    ExportData exportData = new ExportData(titlename,condition,jobBookName,comments,order);
                    if(!contentMerge){
                        exportData.PoiWriteExcel2_To2007(data,dataType,out);
                    }else{
                        exportData.PoiWriteExcel_To2007(data,dataType,out);
                    }
                }else{

                    String[][] comments=JSON.parseObject(JSONArray.toJSONString((JSONArray) map.get("comments")), String[][].class);//获取批注
                    String[][] order=JSON.parseObject(JSONArray.toJSONString((JSONArray) map.get("order")), String[][].class);//数据序列
                    String[] jobBookName=JSON.parseObject(JSONArray.toJSONString((JSONArray) map.get("jobBookName")), String[].class);//工作簿名
                    String[][] dataType=JSON.parseObject(JSONArray.toJSONString((JSONArray) map.get("dataType")), String[][].class);//字段数据类型
                    if (title.length==0||jobBookName.length==0||map.size()==0||order.length==0){
                        throw new NullPointerException("数据格式异常");
                    }
                    ExportData exportData = new ExportData(title, jobBookName, comments);
                    exportData.PoiWriteExcel_To2007(data, order, dataType, out);
                }

                out.flush();
            } finally {
                out.close();
            }
            RedisUtil redisUtil = SpringContextUtil.getBean(RedisUtil.class);
            LedingOutFile leadingOutFile = new LedingOutFile();
            leadingOutFile.setFileName(fileName);
            leadingOutFile.setFilePath(fileFolderName+File.separator+fileNames);
            leadingOutFile.setFileSize(FileUtil.getSize(new File(fileFolderName+File.separator+fileNames)));
            leadingOutFile.setFileTime(fileTime);
            UserInfo userInfo = (UserInfo)redisUtil.get(userId);
            leadingOutFile.setFileUser(userInfo.getUserId());
            LeadingOutService leadingOutService= SpringContextUtil.getBean(LeadingOutService.class);
            leadingOutService.inset(leadingOutFile);
            redisUtil.set(serialNumber,leadingOutFile,86400);
        }catch (Exception e){
            e.printStackTrace();

        }
    }

    /**
     * 路径遍历 漏洞修复
     * @param str
     * @return
     */
    public static String filenameFilter(String str){
        String strInjectListStr = "../|./|/..| |<|>|:|?";
        if(null != strInjectListStr && !"".equals(strInjectListStr)) {
            str = str.toLowerCase();
            String[] badStrs = strInjectListStr.split("\\|");
            for(int i = 0;i < badStrs.length;i++){
                if(str.indexOf(badStrs[i]) >= 0){
                    str = str.replace(badStrs[i],"");
                }
            }
        }
        return str;
    }
}
